package com.mdxq.mall.controller;

import com.mdxq.mall.config.RabbitConfig;
import com.mdxq.mall.config.RabbitConfig2;
import com.mdxq.mall.entity.Person;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.nio.charset.StandardCharsets;

//借助web客户端，向队列中生产各式各样的消息
@RestController
@RequestMapping("/rabbit")
@Slf4j
public class RabbitController {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @PostMapping("updateBalance")
    public String updateBalance(@RequestBody Person person){
        rabbitTemplate.convertAndSend(RabbitConfig2.EXCHANGE_NAME,"person.balance",person);
        return "Success按计划大噶可及时发布";
    }
    @PostMapping("sendMessage1")
    public String t1(String message){
        rabbitTemplate.send("normal_queue",new Message(message.getBytes(StandardCharsets.UTF_8)));
        rabbitTemplate.send("user.info",new Message(message.getBytes(StandardCharsets.UTF_8)));
        return "success~~~~~";
    }
    @PostMapping("sendMessage2")
    public String t2(String message){
        //利用主题交换机和路由键进行消息同步
        rabbitTemplate.send(RabbitConfig.EXCHANGE_NAME,"user.info",
            new Message(message.getBytes(StandardCharsets.UTF_8)));
        return "success发电公司";
    }
    @PostMapping("sendMessage3")
    public String t3(@RequestBody Person person){
        //convertAndSend可以将任意类型的数据转换格式后投递到消息队列
        rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_NAME,"user.info",person);
        return "success卡三个小时了巨大";
    }
    //第一种保证消息可靠性的方式：生产段通过ack响应状态码来判断是否需要重传本消息
    @PostMapping("sendMessage4")
    public String t4(@RequestParam String message){
//        rabbitTemplate.handleConfirm();
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            //参数说明：  消息的唯一标识   是否成功
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String s) {
                //ack如果是true则什么都不做，反之则重传本消息
                if (!ack){
                    rabbitTemplate.send(RabbitConfig.EXCHANGE_NAME,"user.info",
                            new Message(message.getBytes(StandardCharsets.UTF_8)),correlationData);
                }
            }
        });
        rabbitTemplate.send(RabbitConfig.EXCHANGE_NAME,"user.info",
                new Message(message.getBytes(StandardCharsets.UTF_8)),new CorrelationData("101"));
        return "success点击开始给发空间";
    }
    //第二种保证消息可靠性投递的方式return模式：生产端调用returnCallBack方法来重发消息
    @PostMapping("sendMessage5")
    public String t5(@RequestParam String message){
        rabbitTemplate.setMandatory(true);//强制可靠性消息投递
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            //参数：    正在发送的消息    mq返回的响应状态码    相应的说明文本     交换机的名称   路由键
            //如果消息从交换机投递到队列的过程中出现了故障，就会自动回调returnedMessage方法
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                log.info("消息内容：{}",new String(message.getBody(),StandardCharsets.UTF_8));
                log.info("MQ返回的状态码：{}",replyCode);
                log.info("MQ返回的状态文本：{}",replyText);
                log.info("交换机的名称：{}",exchange);
                log.info("路由键：{}",routingKey);
                rabbitTemplate.send(exchange,routingKey,message);
            }
        });
        rabbitTemplate.send(RabbitConfig.EXCHANGE_NAME,"user.info",
                new Message(message.getBytes(StandardCharsets.UTF_8)));
        return "success京哈发噶空间的";
    }
}
